package com.youpai.platform.vulture.service.handler.flag;

import com.alibaba.fastjson.JSONObject;
import com.youpai.platform.chat.service.entity.dto.OfflineEventDTO;
import com.youpai.platform.chat.service.entity.dto.OnlineEventDTO;
import com.youpai.platform.chat.service.service.VultureChatEventFacadeInterface;
import com.youpai.platform.common.exceptions.RemoteException;
import com.youpai.platform.common.util.cache.Cache;
import com.youpai.platform.vulture.common.entity.AccessMessage;
import com.youpai.platform.vulture.common.enums.MsgFlagEnum;
import com.youpai.platform.vulture.service.channel.ChannelAttrs;
import com.youpai.platform.vulture.service.channel.VultureChannel;
import com.youpai.platform.vulture.service.entity.dto.HandShakeDTO;
import com.youpai.platform.vulture.service.handler.vulture.MessageHandler;
import com.youpai.platform.vulture.service.support.DetectionSupport;
import com.youpai.platform.vulture.service.support.VultureChannelSupport;
import com.youpai.platform.vulture.service.util.CacheKeyUtil;
import io.netty.channel.ChannelHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @date: 2022/7/10 17:42
 * @author: Anna
 * @version: 1.0
 * @description: 握手请求处理
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class HandShakeMessageHandler implements MessageHandler {

    @Resource
    @Qualifier(value = "redisCache")
    private Cache<String, String> handShakeTokenCache;
    @Resource
    private VultureChatEventFacadeInterface vultureChatEventFacadeInterface;

    @Override
    public void handle(VultureChannel vultureChannel, AccessMessage accessMessage) throws RemoteException {
        String body = accessMessage.getBody();
        HandShakeDTO handShake = JSONObject.parseObject(body, HandShakeDTO.class);
        checkHandShake(handShake, vultureChannel);
        if (vultureChannel.isActive()) {
            VultureChannelSupport.removeHandShakeChannel(ChannelAttrs.getAttrs(vultureChannel).getAccId());
            publishKickEvent(vultureChannel, handShake);
            reHandShake(vultureChannel, handShake);
        } else {
            handShake(vultureChannel, handShake);
        }
        // 添加到用户账号channel映射表
        VultureChannelSupport.addHandShakeChannel(ChannelAttrs.getAttrs(vultureChannel).getAccId(), vultureChannel);
        // 标记为有效
        vultureChannel.makeActive();
        log.info("握手成功 - {} , attrs - {}", vultureChannel, ChannelAttrs.getAttrs(vultureChannel));
        // 开启心跳
        DetectionSupport.startHeartbeat(vultureChannel);
        // 通知业务方用户连接成功
        notifyBizService(handShake);
        // 给客户端回复握手成功消息
        sendHandShakeMessage(vultureChannel);
    }

    private void removeHandShakeChannel(String accId) {

    }

    private void checkHandShake(HandShakeDTO handShake, VultureChannel vultureChannel) throws RemoteException {
        if (StringUtils.isBlank(handShake.getAccId())) {
            log.error("握手accId为空 - {}", handShake);
            throw new RemoteException(vultureChannel, "握手accId为空");
        }
        if (null == handShake.getAppId()) {
            log.error("握手appId为空 - {}", handShake);
            throw new RemoteException(vultureChannel, "握手appId为空");
        }
        if (null == handShake.getImType()) {
            log.error("握手ImType为空 - {}", handShake);
            throw new RemoteException(vultureChannel, "握手ImType为空");
        }
        if (StringUtils.isBlank(handShake.getDId())) {
            log.error("握手设备id为空 - {}", handShake);
            throw new RemoteException(vultureChannel, "握手设备id为空");
        }
        if (StringUtils.isBlank(handShake.getVultureToken())) {
            log.error("握手token为空 - {}", handShake);
            throw new RemoteException(vultureChannel, "握手token为空");
        }
        if (StringUtils.isBlank(handShake.getVVer())) {
            log.error("握手vultureVersion为空 - {}", handShake);
            throw new RemoteException(vultureChannel, "握手vultureVersion为空");
        }
        if (StringUtils.isBlank(handShake.getCVer())) {
            log.error("握手ClientVersion为空 - {}", handShake);
            throw new RemoteException(vultureChannel, "握手ClientVersion为空");
        }
    }

    private void notifyBizService(HandShakeDTO accessMessage) {
        OnlineEventDTO onlineEventDTO = new OnlineEventDTO();
        onlineEventDTO.setAccId(accessMessage.getAccId());
        vultureChatEventFacadeInterface.onlineEvent(onlineEventDTO);
    }

    private void publishKickEvent(VultureChannel vultureChannel, HandShakeDTO handShake) {
        String msg =
                "用户- " + ChannelAttrs.getAttrs(vultureChannel).getAccId() + ",被用户 -" + handShake.getAccId() + " 踢掉";
        log.info(msg);
        OfflineEventDTO offlineEventDTO = new OfflineEventDTO();
        offlineEventDTO.setAccId(ChannelAttrs.getAttrs(vultureChannel).getAccId());
        vultureChatEventFacadeInterface.offlineEvent(offlineEventDTO);
    }

    private void handShake(VultureChannel vultureChannel, HandShakeDTO handShake) throws RemoteException {
        // 校验token
        verifyToken(vultureChannel, handShake);
        // 初始化channel属性
        initChannelAttrs(vultureChannel, handShake);
    }

    private void reHandShake(VultureChannel vultureChannel, HandShakeDTO handShake) throws RemoteException {
        ChannelAttrs attrs = ChannelAttrs.getAttrs(vultureChannel);
        attrs.reInit(handShake.getAccId());
    }

    private void sendHandShakeMessage(VultureChannel vultureChannel) {
        AccessMessage access = new AccessMessage();
        access.setFlag(MsgFlagEnum.HAND_SHAKE.flag);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", "2000");
        jsonObject.put("msg", "握手成功");
        access.setBody(jsonObject.toJSONString());
        vultureChannel.send(access);
    }

    private void initChannelAttrs(VultureChannel vultureChannel, HandShakeDTO handShake) {
        ChannelAttrs.init(vultureChannel)
                .setAccId(handShake.getAccId())
                .setAppId(handShake.getAppId())
                .setClientVersion(handShake.getCVer())
                .setVultureVersion(handShake.getVVer())
                .setImType(handShake.getImType());
    }

    private void verifyToken(VultureChannel vultureChannel, HandShakeDTO handShake) throws RemoteException {
        String cacheToken = handShakeTokenCache.getValue(CacheKeyUtil.getHandShakeToken(handShake.getDId()),
                String.class);
        if (!handShake.getVultureToken().equalsIgnoreCase(cacheToken)) {
            throw new RemoteException(vultureChannel, "握手token不正确！");
        }
    }
}
